package controller;

import entity.FileSystem;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.config.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import java.io.File;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Controller
public class FileAction {

    @Autowired
    private Redisson redisson;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @RequestMapping("upload")
    public @ResponseBody
    //MultipartHttpServletRequest是httpservletRequest的强化版本，
    //不仅可以装文本信息，还可以装图片信息
    FileSystem upload(MultipartHttpServletRequest request){

        //使用分布式锁
        //定义图片名称
        String imgKey = "img-01";
        //通过redisson获取锁
        RLock rLock = redisson.getLock(imgKey);
        //上锁（过期时间30s
        rLock.lock(30, TimeUnit.SECONDS);


        try{
            //从redis中获取照片的名称
            Set<String> imgs = stringRedisTemplate.opsForSet().members("img01");
            //判断当前照片名称是否在集合内
            //从页面请求中，获取上传的文件对象
            MultipartFile file = request.getFile("fname");
            //从文件对象中获取文件的原始名称
            String oldFileName = file.getOriginalFilename();
            FileSystem fileSystem = new FileSystem();

            if (imgs.contains(oldFileName)){
                return fileSystem;
            }


            //1 把文件保存到web服务器
            //通过字符串截取的方式，从文件原始名中获取文件的后缀
            String hou = oldFileName.substring(oldFileName.lastIndexOf(".") + 1);
            //为了避免文件因为同名而覆盖，生成全新的文件名
            String newFileName = UUID.randomUUID().toString() + "." + hou;

            //创建web服务器保存文件的目录
            File toSaveFile = new File("F:\\Java_Learning\\拉勾java班\\代码\\练习\\stage7\\module2\\upload", newFileName);
            //将路径转换成文件
            file.transferTo(toSaveFile);
            //获取服务器的绝对路径
            String newFilePath = toSaveFile.getAbsolutePath();

            //2 把文件从web服务器上传到FastDFS
            ClientGlobal.initByProperties("config/fastdfs-client.properties");
            TrackerClient trackerClient = new TrackerClient();
            TrackerServer trackerServer = trackerClient.getConnection();
            StorageServer storageServer = null;
            StorageClient1 client = new StorageClient1(trackerServer, storageServer);

            NameValuePair[] list = new NameValuePair[1];
            list[0] = new NameValuePair("fileName",oldFileName);
            String fileId = client.upload_file1(newFilePath, hou, list);
            trackerServer.close();

            //封装fileSystem数据对象
            fileSystem.setFileId(fileId);
            fileSystem.setFileName(oldFileName);
            //已经上传到FastDFS上，通过fileId来访问图片，所以fileId即为文件路径
            fileSystem.setFilePath(fileId);

            //把照片名称存放到集合中
            stringRedisTemplate.opsForSet().add("img01", oldFileName);

            return fileSystem;
        }catch (Exception e){
            e.printStackTrace();
            return new FileSystem();
        }finally {
            //释放锁
            rLock.unlock();
        }
    }

    @Bean
    public Redisson redisson(){
        Config config = new Config();
        // 使用单个redis服务器
        config.useSingleServer().setAddress("redis://192.168.205.128:6379").setDatabase(0);
        // 使用集群redis
        // config.useClusterServers().setScanInterval(2000).addNodeAddress("redis://192.168.204.141:6379","redis://192.168.204.142:6379","redis://192.168.204.143:6379");
        return (Redisson)Redisson.create(config);
    }
}
